﻿using System;
using System.Collections.Generic;
using System.Text;
using com.crawler.common;
using System.Text.RegularExpressions;
using System.Web;
using System.IO;
using System.Threading;

namespace com.crawler.components
{
    public class BaiDuManager
    {
        

        private static object m_syn_obj = new object();

        /// <summary>
        /// 触发发送消息的事件
        /// </summary>
        public event SendMsgEventHandler SendMsg;

        #region 消息回送
        /// <summary>
        /// 发送消息到客户端
        /// </summary>
        /// <param name="i_msg"></param>
        private void SendMsg2Client(object i_msg)
        {
            SendMsgEventArgs e = new SendMsgEventArgs();
            e.Msg = i_msg;
            if (SendMsg != null)
            {
                SendMsg(this, e);
            }

        }
        #endregion

        private string m_top_book_url = "http://top.baidu.com/buzz.php?p=book";

        private string m_hao_top_book_url = "http://book.hao123.com/index//{0}";

        //搜索多少页
        private int m_page_count = 10;

        private string m_hao_reg="<span[^<>]*?list-item[^<>]*?>\\s*?<a[^<>]*?href=s*[\'\"]*([^\"\']*)[\'\"]*[^<>]*?title=s*[\'\"]*([^\"\']*)[\'\"]*[^<>]*?>\\s*?<img[^<>]*?src=s*[\'\"]*([^\"\']*)[\'\"]*[^<>]*?>";

      
   
        DBManager m_db_mgr = new DBManager();

        /// <summary>
        /// 站点列表
        /// </summary>
        List<BookSiteInfo> m_list = null;

        /// <summary>
        /// 系统配置
        /// </summary>
        private SysConfigInfo m_sys_config = null;

        /// <summary>
        /// 需要搜索的小说队列
        /// </summary>
        List<BookInfo> m_seo_book_list = null;

        /// <summary>
        /// 点击100
        /// </summary>
        List<BookInfo> m_click_book_list = null;

        /// <summary>
        /// 每个线程任务量
        /// </summary>
        private int m_per_thd_seo_count = 0;

        /// <summary>
        /// 需要搜索的章节
        /// </summary>
        Queue<BookInfo> m_seo_chapter_list = null;

        /// <summary>
        /// 需要收录的VIP小说
        /// </summary>
        List<BookInfo> m_vip_book_list = null;

        /// <summary>
        /// 需要收录的VIP章节
        /// </summary>
        Queue<BookInfo> m_vip_chapter_list = null;

        /// <summary>
        /// 百度去搜索的小说
        /// </summary>
        List<BookInfo> m_crawler_chapter_list = null;

        /// <summary>
        /// 6个线程收录
        /// </summary>
        Thread[] m_crawler_thd = new Thread[10];



        /// <summary>
        /// 构造函数
        /// </summary>
        public BaiDuManager()
        {
            try
            {
                m_sys_config = SerializationHelper.Load(typeof(SysConfigInfo), Consts.SysConfigFileName) as SysConfigInfo;

                m_list = SerializationHelper.Load(typeof(List<BookSiteInfo>), Consts.SiteFileName) as List<BookSiteInfo>;

            }
            catch (Exception ex)
            {
                LogHelper.Error("加载系统配置失败" + ex.ToString());
            }
        }

        #region 搜索排行榜小说

        /// <summary>
        /// 搜索排行榜小说
        /// </summary>
        public void GetTopBook()
        {
            string t_reg = "<td\\s*?class=[\'\"]*?key[^<>]*?>\\s*?<a[^<>]*?>([^<>]*?)</a>\\s*?</td>";

            string t_html = string.Empty;

            string t_book_name = string.Empty;

            long t_book_id = 0;

            string t_book_url = string.Empty;

            int t_site_id = Consts.qidian;

            SendMsg2Client("开始收录百度排行榜");

            try
            {
                t_html =HttpHelper.GetHttpRequestStringByNUll_Post(m_top_book_url);

                if (!string.IsNullOrEmpty(t_html))
                {
                    MatchCollection t_ma = Regex.Matches(t_html, t_reg, RegexOptions.IgnoreCase | RegexOptions.Compiled);

                    SendMsg2Client(string.Format("获取到{0}本图书信息",t_ma.Count));

                    foreach (Match t_mc in t_ma)
                    {
                        t_book_name = t_mc.Groups[1].Value.ToString().Trim();

                        if (string.IsNullOrEmpty(t_book_name))
                            continue;

                        t_book_id = m_db_mgr.AddTopBook(t_book_name, Consts.BookSource.BaiDu);

                        if (t_book_id == 0)
                        {

                            SendMsg2Client(string.Format("【{0}】入库成功，准备收录图书详情", t_book_name));

                            t_book_url = GetBookUrl(t_book_name);

                            if (string.IsNullOrEmpty(t_book_url))
                            {
                                SendMsg2Client(string.Format("【{0}】没找到图书详情URL", t_book_name));
                                continue;
                            }

                            if (t_book_url.ToLower().IndexOf("qdmm") > -1)
                                t_site_id = Consts.qdmm;

                            List<BookSiteInfo> t_list = m_list.FindAll(delegate(BookSiteInfo t_site_info)
                            {
                                return t_site_info.SiteId == t_site_id;
                            });

                            if (t_list == null || t_list.Count <= 0)
                                continue;

                            t_html =HttpHelper.GetHttpRequestStringByNUll_Post(t_book_url);

                            Match t_mc_book = Regex.Match(t_html, t_list[0].BookReg, RegexOptions.IgnoreCase | RegexOptions.Compiled);

                            BookInfo t_book = ParseBook(t_mc_book, t_list[0], t_book_url);

                            if (t_book != null)
                            {
                                if (string.IsNullOrEmpty(t_book.BookName))
                                    continue;

                              

                                SendMsg2Client(string.Format("图书详情收录成功，小说URL={0}", t_book_url));

                                t_book_id = m_db_mgr.AddBook(t_book);

                                if (t_book_id > 0)
                                {
                                    m_db_mgr.AddBookClick(t_book_id);
                                    //下载封面
                                    if (!string.IsNullOrEmpty(t_book.ICONUrl))
                                    {
                                        NetSiteCatchManager.DownBookICON(t_book.ICONUrl, t_book_id, m_sys_config.ICONPath);
                                    }

                                }
                            }
                        }
                        else
                        {

                            SendMsg2Client(string.Format("【{0}】库里已经存在",t_book_name));
                        }
                    }

                    SendMsg2Client("搜索完成");

                    Thread.Sleep(24 * 60 * 60 * 1000);//一天收录一次
                }
            }
            catch (Exception ex)
            {
                LogHelper.Error("收录排行榜小说失败" + ex.ToString());
            }
        }

        /// <summary>
        /// 获取图书的地址
        /// </summary>
        /// <param name="i_book_name"></param>
        /// <returns></returns>
        private string GetBookUrl(string i_book_name)
        {
            string t_search_url = string.Format("http://www.baidu.com/s?wd={0}", HttpUtility.UrlEncode(string.Format("{0} {1}", i_book_name, "最新章节 起点中文网"), Encoding.UTF8));

            string t_reg_url="qidian\\.com\\/book\\/\\d+\\.aspx|qdmm\\.com\\/book\\/\\d+\\.aspx|\\d+\\.qidian\\.com|\\d+\\.qdmm\\.com|qidian\\.com\\/bookreader\\/\\d+\\.aspx";
            
            try
            {
                
                string t_html =HttpHelper.GetHttpRequestStringByNUll_Post(t_search_url);
                string t_url=string.Empty;

                if (!string.IsNullOrEmpty(t_html))
                {
                    MatchCollection t_ma = Regex.Matches(t_html, "<h3\\s*?class=[\'\"]?t[\'\"]?><a[^<>]*?hrefs*=s*[\'\"]*([^\"\']*)[\'\"]*[^<>]*?>(.*?)</a>\\s*?</h3>", RegexOptions.IgnoreCase | RegexOptions.Compiled);

                    if (t_ma == null || t_ma.Count <= 0)
                        return string.Empty;

                    foreach (Match t_mc in t_ma)
                    {
                        if (t_mc.Groups.Count == 3)
                        {
                            t_url = t_mc.Groups[1].Value.ToString();
                            if (Regex.IsMatch(t_url, t_reg_url, RegexOptions.IgnoreCase | RegexOptions.Compiled))
                                break;
                            t_url = string.Empty;
                        }
                    }
                }

                if (!string.IsNullOrEmpty(t_url) && t_url.ToLower().IndexOf("bookreader") > -1)
                    t_url = Regex.Replace(t_url, "bookreader", "book", RegexOptions.IgnoreCase);

                return t_url;
                   
                
            }
            catch (Exception ex)
            {
                LogHelper.Error("获取网站代码失败" + ex.ToString());
                return string.Empty;
            }
        }

        /// <summary>
        /// 解析小说信息
        /// </summary>
        /// <param name="i_mc"></param>
        /// <param name="i_book_site"></param>
        /// <returns></returns>
        private BookInfo ParseBook(Match i_mc, BookSiteInfo i_book_site,string i_book_url)
        {
            try
            {
                BookInfo t_book = new BookInfo();
                t_book.BookName = i_mc.Groups[i_book_site.BookNameRegIndex2].Value.ToString().Trim().Replace("'", "");
                t_book.AuthorName = i_mc.Groups[i_book_site.AuthorNameRegIndex].Value.ToString().Trim().Replace("'", "");
                t_book.CategoryName = i_mc.Groups[i_book_site.CategoryNameRegIndex].Value.ToString().Trim().Replace("'", "");
                t_book.SubCategoryName = i_mc.Groups[i_book_site.SubCategoryNameRegIndex].Value.ToString().Trim().Replace("'", "");
                t_book.ICONUrl = CrawlerUtil.GetFullUrl(i_book_url, i_mc.Groups[i_book_site.ICONRegIndex].Value.ToString().Trim()).Replace("'", "");
                t_book.ChapterListUrl = CrawlerUtil.GetFullUrl(i_book_url, i_mc.Groups[i_book_site.ChapterListUrlIndex].Value.ToString().Trim()).Replace("'", "");
                t_book.Description = CrawlerUtil.FilterContent(i_mc.Groups[i_book_site.DescriptionRegIndex].Value.ToString().Trim());
                t_book.SiteId = i_book_site.SiteId;
                t_book.SiteName = i_book_site.SiteName;

                return t_book;
            }
            catch (Exception ex)
            {
                LogHelper.Error("解析小说介绍页失败" + ex.ToString());
                return null;
            }
        }


        #endregion

        #region 搜索章节内容

        public void StartTitle()
        {
    

            //Thread t_thd_hao123_top_book = new Thread(GetTOP123Book);
            //t_thd_hao123_top_book.Start();

            if (m_seo_book_list == null || m_seo_book_list.Count == 0)
                SetBook(1);

            Thread t_thd_top_book = new Thread(TheadClickBook);
            t_thd_top_book.Start();

            if (m_seo_book_list != null && m_seo_book_list.Count > 0)
            {
              
                Thread[] t_thd = new Thread[3];

                m_per_thd_seo_count = m_seo_book_list.Count / t_thd.Length;

                for (int index = 0; index < t_thd.Length; index++)
                {
                    t_thd[index] = new Thread(new ParameterizedThreadStart(ThreadSEOBook));
                    t_thd[index].Name = index.ToString();
                    t_thd[index].Start(index);
                   
                }
            }
            
            if (m_vip_book_list == null || m_vip_book_list.Count == 0)
                SetBook(2);

            if (m_vip_book_list != null && m_vip_book_list.Count > 0)
            {
                Thread[] t_vip_thd = new Thread[1];

                for (int index = 0; index < t_vip_thd.Length; index++)
                {
                    t_vip_thd[index] = new Thread(ThreadVIPBook);
                    t_vip_thd[index].Start();
                }
            }
        }

        public void StartContent()
        {
            if (m_crawler_chapter_list == null || m_crawler_chapter_list.Count == 0)
                SetBook(5);

            if (m_crawler_chapter_list == null || m_crawler_chapter_list.Count == 0)
                return;

            //每个线程100本


            for (int index = 0; index < m_crawler_thd.Length; index++)
            {
                m_crawler_thd[index] = new Thread(new ParameterizedThreadStart(ThreadSEOChapterByCrawler));
                m_crawler_thd[index].Name=index.ToString();
                m_crawler_thd[index].Start(index);
                 
            }

      
          
            //Thread[] t_vip_chapter_thd = new Thread[2];

            //for (int index = 0; index < t_vip_chapter_thd.Length; index++)
            //{
            //    t_vip_chapter_thd[index] = new Thread(ThreadVIPChapter);
            //    t_vip_chapter_thd[index].Start();
            //}
        }


        private void ThreadSEOBook(object i_obj)
        {
            int t_index = (int)i_obj;

            for (int index = t_index * m_per_thd_seo_count; index < (t_index + 1) * m_per_thd_seo_count; index++)
            {

                if (index > m_seo_book_list.Count)
                    break;

                BaiDuChapter t_baidu_mgr = new BaiDuChapter();
                t_baidu_mgr.m_list = m_list;
                t_baidu_mgr.m_sys_config = m_sys_config;
                t_baidu_mgr.StartBook(m_seo_book_list[index]);
            }
        }

        private void TheadClickBook()
        {
            int index = 0;
            if (m_click_book_list == null || m_click_book_list.Count <= 0)
                SetBook(1);

            while (true)
            {
                if (index > m_click_book_list.Count - 1)
                    index = 0;
                BaiDuChapter t_baidu_mgr = new BaiDuChapter();
                t_baidu_mgr.m_list = m_list;
                t_baidu_mgr.m_sys_config = m_sys_config;
                t_baidu_mgr.StartBook(m_click_book_list[index]);
                index++;
            }
        }

        private void ThreadSEOChapter()
        {
            BookInfo t_book = null;
        
            if (m_seo_chapter_list == null || m_seo_chapter_list.Count == 0)
                SetBook(3);

            if (m_seo_chapter_list == null || m_seo_chapter_list.Count == 0)
                return;
       
            while (true)
            {
               
                if (m_seo_chapter_list.Count > 0)
                {
                    Monitor.Enter(m_seo_chapter_list);
                    t_book = m_seo_chapter_list.Dequeue();
                    Monitor.Exit(m_seo_chapter_list);
                }
                else
                {
                    SetBook(3);
                    continue;
                }
              

                if (t_book != null)
                {
                    BaiDuChapter t_baidu_mgr = new BaiDuChapter();
                    t_baidu_mgr.m_list = m_list;
                    t_baidu_mgr.m_sys_config = m_sys_config;
                    t_baidu_mgr.StartSEOChatper(t_book.BookId,t_book.SiteId);

                }
            }
        }

        private void ThreadSEOChapterByCrawler(object i_obj)
        {
            int t_index =(int) i_obj ;
   
            for (int index = t_index * 30; index < (t_index + 1) * 30 ; index++)
            {
                if (index > m_crawler_chapter_list.Count)
                {
                    LogHelper.Info("index 溢出");
                    break;
                }
                BaiDuChapter t_baidu_mgr = new BaiDuChapter();
                t_baidu_mgr.m_list = m_list;
                t_baidu_mgr.m_sys_config = m_sys_config;
                t_baidu_mgr.StartSEOChatperByCrawler(m_crawler_chapter_list[index].BookId, m_crawler_chapter_list[index].SiteId);

                LogHelper.Info(string.Format("线程{0} 开始 小说 {1}", t_index, m_crawler_chapter_list[index].BookId));
            }
          
        }

        private void ThreadVIPBook()
        {
           
            for(int index=0;index<m_vip_book_list.Count;index++)
            {
                BaiDuChapter t_baidu_mgr = new BaiDuChapter();
                t_baidu_mgr.m_list = m_list;
                t_baidu_mgr.m_sys_config = m_sys_config;
                t_baidu_mgr.StartBook(m_vip_book_list[index]);
                
            }
        }

        private void ThreadVIPChapter()
        {
            BookInfo t_book = null;

            if (m_vip_chapter_list == null || m_vip_chapter_list.Count == 0)
                SetBook(4);

            while (true)
            {
              
                if (m_vip_chapter_list.Count > 0)
                {
                    Monitor.Enter(m_vip_chapter_list);
                    t_book = m_vip_chapter_list.Dequeue();
                    Monitor.Exit(m_vip_chapter_list);
                }
                else
                {
                    SetBook(4);
                    continue;
                }
              
                if (t_book != null)
                {
                    BaiDuChapter t_baidu_mgr = new BaiDuChapter();
                    t_baidu_mgr.m_list = m_list;
                    t_baidu_mgr.m_sys_config = m_sys_config;
                    t_baidu_mgr.StartSEOChatper(t_book.BookId,t_book.SiteId);
                }
            }
        }



        /// <summary>
        /// 搜索章节列表
        /// </summary>
        private void SetBook(int i_type)
        {
            try
            {
                if (i_type == 1)
                {
                   
                    List<BookInfo> t_list = m_db_mgr.GetSEOBook();

                    if (t_list != null && t_list.Count > 0)
                    {
                        m_click_book_list = new List<BookInfo>();

                        m_seo_book_list = new List<BookInfo>();

                        m_click_book_list.AddRange(t_list.GetRange(0, 100));

                        m_seo_book_list.AddRange(t_list.GetRange(100, t_list.Count - 101));
                    }
                  
                    if (m_seo_book_list == null || m_seo_book_list.Count <= 0)
                    {
                        SendMsg2Client("没有需要收录章节的小说");
                        return;
                    }
                    else
                    {
                        SendMsg2Client(string.Format("需要收录{0}个小说", m_seo_book_list.Count));
                        LogHelper.Info(string.Format("需要收录{0}个小说", m_seo_book_list.Count));
                    }
                   
                }
                else if (i_type == 2)
                {
                    m_vip_book_list = m_db_mgr.GetVIPBook();
                    if (m_vip_book_list == null || m_vip_book_list.Count <= 0)
                    {
                        SendMsg2Client("没有需要收录VIP章节的小说");
                        return;
                    }
                    else
                    {
                        SendMsg2Client(string.Format("需要收录{0}个VIP小说", m_vip_book_list.Count));
                        LogHelper.Info(string.Format("需要收录{0}个VIP小说", m_vip_book_list.Count));
                    }
                }
                else if (i_type == 5)
                {
                   
                        m_crawler_chapter_list = m_db_mgr.GetSEOBookChapterContent();
                       if (m_crawler_chapter_list == null || m_crawler_chapter_list.Count <= 0)
                        {
                            SendMsg2Client("没有需要收录章节内容的小说");
                            return;
                        }
                        else
                        {
                            SendMsg2Client(string.Format("百度需要收录{0}个小说的章节内容", m_crawler_chapter_list.Count));
                            LogHelper.Info(string.Format("百度需要收录{0}个小说的章节内容", m_crawler_chapter_list.Count));
                        }
                }
              

               
            }
            catch (Exception ex)
            {
                LogHelper.Error("从搜索引擎搜索小说出现异常" + ex.ToString());
            }
        }

       

        #endregion

        #region 替换章节内容
        public void ReplaceContent()
        {
            SendMsg2Client("操作开始");

            ReplaceDir(m_sys_config.BookIndexPath);

            SendMsg2Client("操作结束");
        }

        private void ReplaceDir(string i_dir_path)
        {
            DirectoryInfo t_dir_path = new DirectoryInfo(i_dir_path);

            string t_text = string.Empty;
            foreach (FileInfo t_file in t_dir_path.GetFiles("*.txt"))
            {
                try
                {
                    using (StreamReader t_sm_read = new StreamReader(t_file.FullName, System.Text.Encoding.Default))
                    {
                        t_text = t_sm_read.ReadToEnd();
                    }

                    MatchCollection t_ma = Regex.Matches(t_text, "document.write\\('(.*?)'\\);", RegexOptions.IgnoreCase | RegexOptions.Compiled);

                    if (t_ma != null && t_ma.Count > 1)
                    {
                        t_text = string.Format("document.write('{0}');", t_ma[0].Groups[1].Value.ToString());
                        using (FileStream t_file_stream = new FileStream(t_file.FullName, FileMode.Create, FileAccess.Write))
                        {
                            using (StreamWriter t_writer = new StreamWriter(t_file_stream, Encoding.Unicode))
                            {
                                t_writer.WriteLine(t_text);
                                t_writer.Flush();
                                t_writer.Close();
                            }
                        }
                    }
                    
                }
                catch (Exception ex)
                {
                    LogHelper.Error("读取文件出现异常" + ex.ToString());
                
                }
            }

            foreach (DirectoryInfo t_sub_dir in t_dir_path.GetDirectories())
            {
                ReplaceDir(t_sub_dir.FullName);
            }
        }
        #endregion

        #region 搜索hao123的小说

        public void GetTOP123Book()
        {
            try
            {
                for (int index = 1; index <= m_page_count; index++)
                {
                    GetPageBook(string.Format(m_hao_top_book_url, index));
                }
            }
            catch (Exception ex)
            {
                LogHelper.Error("搜索hao123小说失败" + ex.ToString());
            }
        }

        private void GetPageBook(string i_page_url)
        {
            try
            {
                string t_html = HttpHelper.GetHttpRequestStringByNUll_Post(i_page_url);

                string t_book_name = string.Empty;
                string t_book_url = string.Empty;
                string t_book_icon = string.Empty;

                Uri t_uri = null;

                long t_book_id = 0;

                if (!string.IsNullOrEmpty(t_html))
                {
                    MatchCollection t_ma = Regex.Matches(t_html, m_hao_reg, RegexOptions.IgnoreCase | RegexOptions.Compiled);

                    foreach (Match t_mc in t_ma)
                    {
                        if (t_mc.Groups.Count >= 3)
                        {
                            t_book_name = t_mc.Groups[2].Value.ToString().Trim();
                            t_book_icon = t_mc.Groups[3].Value.ToString().Trim();
                            t_book_url = t_mc.Groups[1].Value.ToString().Trim();

                            if (string.IsNullOrEmpty(t_book_name))
                                continue;

                            t_book_id = m_db_mgr.AddTopBook(t_book_name, Consts.BookSource.Hao123);

                            if (t_book_id > 0)
                                continue;

                            t_uri = new Uri(t_book_url);

                            List<BookSiteInfo> t_list = m_list.FindAll(delegate(BookSiteInfo t_site_info)
                            {
                                Uri t_list_uri = new Uri(string.Format(t_site_info.BookListUrl, 1));
                                if (t_list_uri.Host.ToLower() == t_uri.Host.ToLower())
                                    return true;
                                return false;
                              
                            });

                            if (t_list == null || t_list.Count <= 0)
                                continue;

                            t_html = HttpHelper.GetHttpRequestStringByNUll_Post(t_book_url);

                            Match t_mc_book = Regex.Match(t_html, t_list[0].BookReg, RegexOptions.IgnoreCase | RegexOptions.Compiled);

                            BookInfo t_book = ParseBook(t_mc_book, t_list[0], t_book_url);

                            if (t_book != null)
                            {
                                if (string.IsNullOrEmpty(t_book.BookName))
                                    continue;

                                SendMsg2Client(string.Format("图书详情收录成功，小说URL={0}", t_book_url));

                                t_book_id = m_db_mgr.AddBook(t_book);

                                if (t_book_id > 0)
                                {
                                    m_db_mgr.AddBookClick(t_book_id);
                                    //下载封面
                                    if (!string.IsNullOrEmpty(t_book.ICONUrl))
                                    {
                                        NetSiteCatchManager.DownBookICON(t_book_icon, t_book_id, m_sys_config.ICONPath);
                                    }

                                }
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                LogHelper.Error("搜索hao123小说失败" + i_page_url + ex.ToString());
            }
        }

        #endregion

    }
}
